package cn.itcast.account.service.impl;

import cn.itcast.account.entity.AccountFreeze;
import cn.itcast.account.mapper.AccountFreezeMapper;
import cn.itcast.account.mapper.AccountMapper;
import cn.itcast.account.service.AccountTCCService;
import io.seata.core.context.RootContext;
import io.seata.rm.tcc.api.BusinessActionContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Slf4j
@Service
public class AccountTCCServiceImpl implements AccountTCCService {

    @Autowired
    private AccountMapper accountMapper;
    @Autowired
    private AccountFreezeMapper accountFreezeMapper;

    /**
     * try
     * @param userId
     * @param money
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void doTry(String userId, int money) {
        log.info("开始执行try操作===");
//        获取全局事务id
        String xid = RootContext.getXID();
//        防止业务悬挂，先查询冻结表，
        AccountFreeze accountFreeze = accountFreezeMapper.selectById(xid);
        if(accountFreeze != null){
//            如果有数据结束,已经做过cancel，结束
            log.info("已经回滚过了，结束");
            return;
        }
//        记录冻结数据
        accountFreeze = new AccountFreeze();
        accountFreeze.setXid(xid);
        accountFreeze.setUserId(userId);
        accountFreeze.setFreezeMoney(money);
        accountFreeze.setState(AccountFreeze.State.TRY);
        accountFreezeMapper.insert(accountFreeze);
//        扣减account的金额
        accountMapper.deduct(userId, money);
    }

    /**
     * 提交
     * @param ctx
     * @return
     */
    @Override
    public boolean confirm(BusinessActionContext ctx) {
        log.info("开始执行 confirm");
//        从上下文中获取xid
        String xid = ctx.getXid();
        log.info("要删除的xid={}",xid);
//        删除冻结表数据
        int i =  accountFreezeMapper.deleteById(xid);
        return i==1;
    }

    /**
     * 回滚
     * @param ctx
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean cancel(BusinessActionContext ctx) {
        log.info("开始执行 cancel");
        String xid = ctx.getXid();
        String userId = ctx.getActionContext("userId").toString();
        Integer money = Integer.valueOf(ctx.getActionContext("money").toString());
//        根据xid查询 冻结记录
        AccountFreeze accountFreeze = accountFreezeMapper.selectById(xid);
        if(accountFreeze == null) {
//        实现空回滚,新增回滚记录
            accountFreeze = new AccountFreeze();
            accountFreeze.setXid(xid);
            accountFreeze.setUserId(userId);
            accountFreeze.setFreezeMoney(0);
            accountFreeze.setState(AccountFreeze.State.CANCEL);
            accountFreezeMapper.insert(accountFreeze);
            return true;
        }
        if(accountFreeze.getState() == AccountFreeze.State.CANCEL){
//            已经是回滚状态，结束
            log.info("已经是回滚状态，结束");
            return true;
        }
        Integer freezeMoney = accountFreeze.getFreezeMoney();
//        修改冻结表的金额为0 ，状态 2-cancel
        accountFreeze.setState(AccountFreeze.State.CANCEL);
        accountFreeze.setFreezeMoney(0);
        accountFreezeMapper.updateById(accountFreeze);
//        修改account表，恢复金额  =冻结金额 + 当前金额
        accountMapper.refund(userId,freezeMoney);
        return true;
    }
}
